
def flatten_json(rule_objects):
    """
    将规则对象数组扁平化为flat_data格式
    Args:
        rule_objects: 规则对象数组，格式为 [ruleObj1, ruleObj2, ...]
                     每个ruleObj应该包含rule_id字段
    Returns:
        list: 扁平化数据，格式为 [[rule_id, key, type, value], ...]
    """
    all_items = []
    
    # 确保输入是列表
    if not isinstance(rule_objects, list):
        rule_objects = [rule_objects]
    
    # 遍历每个规则对象
    for rule_obj in rule_objects:
        if not isinstance(rule_obj, dict):
            continue
            
        # 从规则对象中提取rule_id
        rule_id = None
        for key in ['rule_id', 'ruleId', 'id', 'Rule_ID']:
            if key in rule_obj:
                rule_id = str(rule_obj[key])
                break
        
        # 如果没有找到rule_id，跳过这个对象
        if rule_id is None:
            continue
            
        # 对当前规则对象进行扁平化
        flattened_items = _flatten_single_object(rule_obj, '', rule_id)
        all_items.extend(flattened_items)
    
    return all_items

def _flatten_single_object(obj, parent_key='', rule_id=''):
    """
    扁平化单个对象的内部函数
    """
    items = []
    
    if isinstance(obj, dict):
        for k, v in obj.items():
            new_key = f"{parent_key}.{k}" if parent_key else k
            items.extend(_flatten_single_object(v, new_key, rule_id))
    elif isinstance(obj, list):
        if len(obj) == 0:
            # 处理空列表：添加特殊标记
            items.append([rule_id, parent_key, 'empty_list', '[]'])
        else:
            for i, item in enumerate(obj):
                new_key = f"{parent_key}#{i}"
                items.extend(_flatten_single_object(item, new_key, rule_id))
    else:
        # 叶子节点，确定数据类型并转换值
        if isinstance(obj, bool):
            data_type = 'bool'
            # 将bool值转换为字符串，以便数据库存储
            value = 'true' if obj else 'false'
        elif isinstance(obj, (int, float)):
            data_type = 'number'
            value = str(obj)  # 将数字转换为字符串
        else:
            data_type = 'str'
            value = str(obj) if obj is not None else None
        items.append([rule_id, parent_key, data_type, value])
    return items

def unflatten_json(flat_data):
    """
    将扁平化数据还原为JSON对象
    Args:
        flat_data: 扁平化数据，格式为以下两种之一：
         1. list of list [[rule_id, key, type, value], ...]
         2. list of dict [{"rule_id": ..., "key": ..., "type": ..., "value": ...}, ...]
    Returns:
        list: 还原后的JSON对象数组，每个元素是一个完整的规则对象
    """
    # 统一转换为 list of list 格式
    if isinstance(flat_data, list) and len(flat_data) > 0 and isinstance(flat_data[0], dict):
        flat_data = [[item.get('rule_id', ''), item.get('key', ''), item.get('type', ''), item.get('value', None)] for item in flat_data]

    result = {}
    for rule_id, key, data_type, value in flat_data:
        if rule_id not in result:
            result[rule_id] = {}
        # 解析路径并设置值
        _set_nested_value(result[rule_id], key, value, data_type)
    
    # 将字典转换为数组，每个规则对象包含其ruleId
    rule_list = []
    for rule_id, rule_obj in result.items():
        # 确保每个规则对象都有ruleId字段
        rule_obj['ruleId'] = rule_id
        rule_list.append(rule_obj)
    
    return rule_list

def _set_nested_value(obj, path, value, data_type):
    """
    根据路径在嵌套对象中设置值
    Args:
        obj: 目标对象
        path: 路径字符串，如 "ruleActs#0.filter#1.value#0"
        value: 要设置的值
        data_type: 数据类型 ('str', 'bool', 'number', 'empty_list')
    """
    # 处理空列表特殊情况
    if data_type == 'empty_list':
        # 解析路径并设置空列表
        parts = _parse_path(path)
        current = obj
        
        # 导航到父级
        for i, part in enumerate(parts[:-1]):
            if isinstance(part, int):
                while len(current) <= part:
                    current.append({})
                if not isinstance(current[part], (dict, list)):
                    current[part] = {} if isinstance(parts[i+1], str) else []
                current = current[part]
            else:
                if part not in current:
                    next_part = parts[i+1] if i+1 < len(parts) else None
                    current[part] = [] if isinstance(next_part, int) else {}
                current = current[part]
        
        # 设置空列表
        final_key = parts[-1]
        if isinstance(final_key, int):
            while len(current) <= final_key:
                current.append(None)
            current[final_key] = []
        else:
            current[final_key] = []
        return
    
    # 转换数据类型
    if data_type == 'bool':
        if isinstance(value, str):
            # 智能识别各种布尔值格式
            lower_value = value.lower().strip()
            converted_value = lower_value in ('true', '1', 'yes', 'on', 'y', 't')
        elif isinstance(value, (int, float)):
            # 数字类型：非0为True，0为False
            converted_value = bool(value)
        else:
            converted_value = bool(value)
    elif data_type == 'number':
        if isinstance(value, str):
            try:
                # 先尝试转换为整数，如果包含小数点则转换为浮点数
                if '.' in value:
                    converted_value = float(value)
                else:
                    converted_value = int(value)
            except ValueError:
                converted_value = value  # 转换失败时保持原值
        else:
            converted_value = value
    else:
        converted_value = str(value) if value is not None else value
    
    # 解析路径
    parts = _parse_path(path)
    
    # 根据路径设置值
    current = obj
    for i, part in enumerate(parts[:-1]):
        if isinstance(part, int):
            # 数组索引
            while len(current) <= part:
                current.append({})
            if not isinstance(current[part], (dict, list)):
                current[part] = {} if isinstance(parts[i+1], str) else []
            current = current[part]
        else:
            # 对象键
            if part not in current:
                # 判断下一个部分是数组索引还是对象键
                next_part = parts[i+1] if i+1 < len(parts) else None
                current[part] = [] if isinstance(next_part, int) else {}
            current = current[part]
    
    # 设置最终值
    final_key = parts[-1]
    if isinstance(final_key, int):
        while len(current) <= final_key:
            current.append(None)
        current[final_key] = converted_value
    else:
        current[final_key] = converted_value

def _parse_path(path):
    """解析路径字符串为parts列表"""
    parts = []
    current_part = ""
    i = 0
    while i < len(path):
        if path[i] == '.':
            if current_part:
                parts.append(current_part)
                current_part = ""
        elif path[i] == '#':
            if current_part:
                parts.append(current_part)
                current_part = ""
            # 找到数组索引
            i += 1
            index_str = ""
            while i < len(path) and path[i].isdigit():
                index_str += path[i]
                i += 1
            parts.append(int(index_str))
            i -= 1  # 因为外层循环会 i += 1
        else:
            current_part += path[i]
        i += 1
    
    if current_part:
        parts.append(current_part)
    
    return parts
